///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include <UI/Container.h>
//-----------------------------------------------------------------------------

Container::Container()
{
	m_parent = NULL;
	m_absPosX = m_absPosY = m_posX = m_posY = m_width = m_height = 0;

	m_color[0] = m_color[1] = m_color[3] = 0;
	m_color[4] = 128;

	m_parent = NULL;
}

//-----------------------------------------------------------------------------

Container::~Container()
{
	std::vector<Container*>::iterator it;
	for( it = m_children.begin(); it != m_children.end(); it++ )
	{
		SAFE_DEL(*it);
	}
}

//-----------------------------------------------------------------------------

void	Container::Update(f32 dt)
{
	if( m_parent )
	{
		m_absPosX = m_parent->GetAbsX() + m_posX;
		m_absPosY = m_parent->GetAbsY() + m_posY;
	}
	else
	{
		m_absPosX = m_posX;
		m_absPosY = m_posY;
	}

	std::vector<Container*>::iterator it;
	for( it = m_children.begin(); it != m_children.end(); it++ )
	{
		(*it)->Update( dt );
	}
}

//-----------------------------------------------------------------------------

void	Container::Draw()
{
	glPushMatrix();
	glTranslatef( (f32)m_posX, (f32)-m_posY, 0.0f);

	if( m_width && m_height )
	{
		glColor3ubv( m_color );
		glBegin( GL_LINE_LOOP );
		glVertex2i(0,0);
		glVertex2i(m_width,0);
		glVertex2i(m_width,-m_height);
		glVertex2i(0,-m_height);
		glEnd();

		//glEnable( GL_BLEND );
		//glColor4ubv( m_color );
		////glColor4ub( 128,0,0, 128 );
		//glBegin( GL_QUADS );
		//glVertex2i(0,-m_height);
		//glVertex2i(m_width,-m_height);
		//glVertex2i(m_width,0);
		//glVertex2i(0,0);
		//glEnd();
	}

	std::vector<Container*>::iterator it;
	for( it = m_children.begin(); it != m_children.end(); it++ )
	{
		(*it)->Draw();
	}

	glPopMatrix();
}

//-----------------------------------------------------------------------------

Container*	Container::GetParent()
{
	return m_parent;
}

//-----------------------------------------------------------------------------

void	Container::SetParent(Container* parent)
{
	m_parent = parent;
}

//-----------------------------------------------------------------------------

void	Container::AddChild(Container* child)
{
	std::vector<Container*>::iterator it;
	for( it = m_children.begin(); it != m_children.end(); it++ )
	{
		if( (*it) == child )
			return;
	}
	m_children.push_back( child );
	child->SetParent( this );
	UpdateFromChild( child );
	child->UpdateFromParent();
}

//-----------------------------------------------------------------------------

void	Container::UpdateFromChild(Container* child)
{
	bool changed = false;
	if( m_width < child->GetX() + child->GetWidth() )
	{
		m_width = child->GetX() + child->GetWidth();
		changed = true;
	}
	if( m_height < child->GetY() + child->GetHeight() )
	{
		m_height = child->GetY() + child->GetHeight();
		changed = true;
	}
	if( changed &&  m_parent )
	{
		m_parent->UpdateFromChild( this );
	}
}

//-----------------------------------------------------------------------------

void	Container::UpdateFromParent()
{
	ASSERT( m_parent );
	if( m_absPosX != m_parent->GetAbsX() + m_posX
		|| m_absPosY != m_parent->GetAbsY() + m_posY)
	{
		m_absPosX = m_parent->GetAbsX() + m_posX;
		m_absPosY = m_parent->GetAbsY() + m_posY;

		UpdateChildren();
	}
}

//-----------------------------------------------------------------------------

void	Container::UpdateChildren()
{
	std::vector<Container*>::iterator it;
	for( it = m_children.begin(); it != m_children.end(); it++ )
	{
		(*it)->UpdateFromParent();
	}
}

//-----------------------------------------------------------------------------

Container*		Container::GetContainerAt(s16 x, s16 y)
{
	if( x >= m_absPosX && x <= m_absPosX + m_width
		&& y >= m_absPosY && y <= m_absPosY + m_height )
	{
		Container* inner = NULL;

		std::vector<Container*>::iterator it;
		for( it = m_children.begin(); it != m_children.end(); it++ )
		{
			if( inner = (*it)->GetContainerAt( x, y ) )
			{
				break;
			}
		}

		if( !inner )
		{
			inner = this;
		}
		return inner;
	}
	return NULL;
}

//-----------------------------------------------------------------------------

void	Container::SetPosition(s16 x, s16 y)
{
	if( m_posX != x
		|| m_posY != y )
	{
		m_posX = x;
		m_posY = y;

		if( m_parent ) UpdateFromChild( this );
		UpdateFromParent();
	}
}

//-----------------------------------------------------------------------------

void	Container::Move(s16 x, s16 y)
{
	if( x != 0 || y != 0 )
	{
		if( m_posX + x < 0 )
		{
			x -= m_posX + x;
		}
		if( m_posY + y < 0 )
		{
			y -= m_posY + y;
		}

		if( m_parent )
		{
			if( m_posX + m_width + x > m_parent->GetWidth() )
			{
				x -= m_posX + m_width + x - m_parent->GetWidth();
			}
			if( m_posY + m_height + y > m_parent->GetHeight() )
			{
				y -= m_posY + m_height + y - m_parent->GetHeight();
			}
		}

		m_posX += x;
		m_posY += y;
		m_absPosX += x;
		m_absPosY += y;

		UpdateChildren();
	}
}

//-----------------------------------------------------------------------------

void	Container::SetSize(s16 width, s16 height)
{
	if( m_width != width
		|| m_height != height )
	{
		m_width = width;
		m_height = height;

		if( m_parent ) UpdateFromChild( this );
		UpdateChildren();
	}
}

//-----------------------------------------------------------------------------

void	Container::SetX(s16 x)
{
	if( m_posX != x )
	{
		m_posX = x;

		if( m_parent ) UpdateFromChild( this );
		UpdateFromParent();
	}
}

//-----------------------------------------------------------------------------

void	Container::SetY(s16 y)
{
	if( m_posY != y )
	{
		m_posY = y;

		if( m_parent ) UpdateFromChild( this );
		UpdateFromParent();
	}
}

//-----------------------------------------------------------------------------

void	Container::SetWidth(s16 width)
{
	if( m_width != width )
	{
		m_width = width;

		if( m_parent ) UpdateFromChild( this );
	}
}

//-----------------------------------------------------------------------------

void	Container::SetHeight(s16 height)
{
	if( m_height != height )
	{
		m_height = height;

		if( m_parent ) UpdateFromChild( this );
	}
}

//-----------------------------------------------------------------------------

s16		Container::GetX()
{
	return m_posX;
}

//-----------------------------------------------------------------------------

s16		Container::GetY()
{
	return m_posY;
}

//-----------------------------------------------------------------------------

s16		Container::GetAbsX()
{
	return m_absPosX;
}

//-----------------------------------------------------------------------------

s16		Container::GetAbsY()
{
	return m_absPosY;
}

//-----------------------------------------------------------------------------

s16		Container::GetWidth()
{
	return m_width;
}

//-----------------------------------------------------------------------------

s16		Container::GetHeight()
{
	return m_height;
}

//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
